package com.company.restaurant.service.codec;

import com.company.restaurant.dto.BaseMessage;
import com.company.restaurant.dto.LoginRequest;
import com.company.restaurant.dto.MessageIds;
import com.company.restaurant.dto.MessageWrapper;
import com.company.restaurant.dto.util.Packager;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.ByteBuffer;
import java.util.List;

/**
 * Description of class.
 * Created 3/27/14 2:43 PM
 *
 * @author andrey.rodin@playtech.com
 */

@Service
public class ByteCodec extends ByteToMessageCodec<BaseMessage> {
    private static final Logger logger = LoggerFactory.getLogger(ByteCodec.class);
    private static final int SIZE_HEADER_BUFFER = 12;

    @Autowired
    private Gson gson = new Gson();

    @Override
    protected void encode(ChannelHandlerContext ctx, BaseMessage msg, ByteBuf out) throws Exception {
        String json = gson.toJson(msg);
        byte[] bytes = json.getBytes(CharsetUtil.UTF_8);
        out.writeInt(bytes.length).writeBytes(bytes);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in.readableBytes() < SIZE_HEADER_BUFFER) {
            return;
        }
        MessageWrapper messageWrapper = parseByteStream(in);
        if (messageWrapper != null) {
            out.add(messageWrapper);
        }
    }

    private MessageWrapper parseByteStream(ByteBuf in) {
        int messageIdSize = 4, protocolSize = 4, messageLength = 4;

        byte[] msgId = new byte[messageIdSize];
        in.readBytes(msgId, 0, messageIdSize);
        int code = ByteBuffer.wrap(msgId).getInt();

        byte[] protSize = new byte[protocolSize];
        in.readBytes(protSize, 0, protocolSize);
        int protCode = ByteBuffer.wrap(protSize).getInt();

        byte[] sizeMsg = new byte[messageLength];
        in.readBytes(sizeMsg, 0, messageLength);
        int size = ByteBuffer.wrap(sizeMsg).getInt();

        byte[] msgByte = new byte[size];
        if (size != in.readableBytes()) {
            return null;
        }
        in.readBytes(msgByte, 0, size);
        MessageWrapper messageWrapper = Packager.unpackFromByteArray(code, protCode, msgByte);
        return messageWrapper;
    }

}
